<?PHP
namespace
{
	require_once dirname(__FILE__) . "/config.php";
	require_once dirname(__FILE__) . "/auroracore/auroracore.php";
	
	require_once dirname(__FILE__) . "/dbaurora/dbaurora.php";
}

// ============= Domain Layer ===================
namespace Aurora\Types
{
   class AccountItem
   {
      private $accountId;

      private $id;
      private $webAccountId;
      private $enabled;
      private $accountType;
      private $failedLogins;
      private $name;
      private $middleName;
      private $lastName;
      private $emailAddress;
      
      public function __construct($args)
      {
         $this->id = $args['ID'];
         $this->accountId = $args['ACCOUNT_ID'];
         $this->webAccountId = isset($args['WEB_ACCOUNT_ID']) ? $args['WEB_ACCOUNT_ID'] : NULL;
         $this->enabled = $args['ENABLED'] === "1" ? TRUE : FALSE;
         $this->accountType = $args['ACCOUNT_TYPE'];
         $this->failedLogins = isset($args['FAILED_LOGINS']) ? $args['FAILED_LOGINS'] : NULL;
         $this->name = isset($args['NAME']) ? $args['NAME'] : NULL;
         $this->middleName = isset($args['MIDDLE_NAME']) ? $args['MIDDLE_NAME'] : NULL;
         $this->lastName = isset($args['LAST_NAME']) ? $args['LAST_NAME'] : NULL;
         $this->emailAddress = isset($args['EMAIL_ADDRESS']) ? $args['EMAIL_ADDRESS'] : NULL;
      }
      
      // put getters/setters here
      public function getAccountId()
      {
         return $this->accountId;
      }

      public function getWebAccountId()
      {
         return $this->webAccountId;
      }

      public function isEnabled()
      {
         return $this->enabled;
      }

      public function exportVars()
      {
         return get_object_vars($this);
      }

      public function __toString()
      {
         return json_encode(get_object_vars($this));
      }
   }

   class RightItem
   {
      private $rightId;

      private $level1;
      private $level2;
      private $level3;
      private $code;
      private $reference;
      private $descripton;

      public function __construct($args)
      {
         $this->rightId = $args['RIGHT_ID'];
         $this->level1 = isset($args['LEVEL1']) ? $args['LEVEL1'] : NULL;
         $this->level2 = isset($args['LEVEL2']) ? $args['LEVEL2'] : NULL;
         $this->level3 = isset($args['LEVEL3']) ? $args['LEVEL3'] : NULL;
         $this->code = isset($args['CODE']) ? $args['CODE'] : NULL;
         $this->reference = isset($args['REFERENCE']) ? $args['REFERENCE'] : NULL;;
         $this->descripton = isset($args['DESCRIPTION']) ? $args['DESCRIPTION'] : NULL;
      }

      public function exportVars()
      {
         return get_object_vars($this);
      }
   }
}

namespace Aurora // Domain Models
{
   use \DB;

   class Manager
   {
      /**
       * @var string[]
       */
      private static $managerNames = array();

      public static function get($mangerName)
      {
         $name = static::$managerNames[$mangerName];
         $r = new \ReflectionClass($name);
         $inst = $r->newInstance();
         
         return $inst;
      }
      
      public static function registerManager($name, $type)
      {
         static::$managerNames[$name] = $type;
      }
      
   }
   
   class StateContext
   {
      private $state = array();
      
      public function restore($query, $session, $cookie)
      {
         $this->state = func_get_args();
      }
      
      public function get($key)
      {
         return $this->state;
      }
   }
   
   class AccountsManager
   {
      public function getAccounts()
      {
         $accounts = DB\Aurora::getRepository("AccountsRepository");
         
         $records = $accounts->findAll(10, 5);

         $res = array_map(function($record) {

            $item = new Types\AccountItem($record);

            return $item;
         }, $records);
         
         return $res;
      }
      
      public function getActiveAccounts($from=0, $count=10)
      {
         $accounts = DB\Aurora::getRepository("AccountsRepository");
         
         $records = $accounts->find("ENABLED = :e", array("e" => 1), $from, $count);

         $res = array_map(function($record) {

            $item = new Types\AccountItem($record);

            return $item;
         }, $records);
         
         return $res;
      }

      public function findById($customId, $from, $count)
      {
         $accounts = DB\Aurora::getRepository("AccountsRepository");

         $records = $accounts->find("ID LIKE :id", array("id" => $customId), $from, $count);

         $res = array_map(function($record) {

            $item = new Types\AccountItem($record);

            return $item;
         }, $records);

         return $res;
      }

      public function getByAccountId($accountId)
      {
         $accounts = DB\Aurora::getRepository("AccountsRepository");

         $record = $accounts->getById($accountId);

         $item = new Types\AccountItem($record);

         return $item;
      }

      /**
       * @param \Aurora\Types\AccountItem $accountItem
       */
      public function saveAccount($accountItem)
      {
         $accounts = DB\Aurora::getRepository("AccountsRepository");

         $item = $accounts->getById($accountItem->getAccountId());

         if (empty($item))
         {
            $item = $accounts->createRecord();
         }

         $fields = array(
            "WEB_ACCOUNT_ID" => $accountItem->getWebAccountId(),
            "ENABLED" => $accountItem->isEnabled() ? "1" : "0"
         );

         $accounts->updateRecord($item['ACCOUNT_ID'], $fields);
      }

      /**
       * @param \Aurora\Types\AccountItem $accountItem
       *
       * @return \Aurora\Types\RightItem
       */
      public function getAccountRights($accountItem)
      {
         $accounts = DB\Aurora::getRepository("AccountsRepository");

         $rights = $accounts->getAccountRights($accountItem->getAccountId());
         $res = array_map(function($record) {

            $item = new Types\RightItem($record);

            return $item;
         }, $rights);

         return $res;
      }
   }
   
   Manager::registerManager("AccountsManager", "\\Aurora\\AccountsManager");

   class AuthManager
   {
      public function Login($login, $password)
      {
         $accounts = DB\Aurora::getRepository("AccountsRepository");

         $records = $accounts->find("ID = :id", array("id" => $login), 0, 1);
         if (!empty($records))
         {
            $record = reset($records);

            $pass = $record['PASSWORD'];

            return TRUE;//$pass === $password;
         }

         return FALSE;
      }
   }

   Manager::registerManager("AuthManager", "\\Aurora\\AuthManager");

   class RolesManager
   {
       public function getByName($name)
	   {
           $roles = DB\Aurora::getRepository("RolesRepository");
		   
		   return NULL;
	   }
	   
	   public function validateRole($roleName)
	   {
	       return FALSE;
	   }
   }

   Manager::registerManager("RolesManager", "\\Aurora\\RolesManager");

   class Session
   {
      private static $inst = NULL;

      /**
       * @return StateContext
       */
      public static function get()
      {
         if (static::$inst === NULL)
         {
            static::$inst = new StateContext();
         }
         
         return static::$inst;
      }
   }
}

// ================ Web service applications/views =================
namespace Aurora\Models
{
   class LoginModel
   {
      private $title = "::Login";
	  
	  private $failure = "";

      private $login;
      private $email;
      private $password;

      public function getLogin()
      {
         return $this->login;
      }

      public function getPassword()
      {
         return $this->password;
      }
	  
	  public function setFailure($value)
	  {
		 $this->failure = $value;
	  }

      public function fillFromArray($fields)
      {
         $this->login = isset($fields['login']) ? $fields['login'] : NULL;
         $this->email = isset($fields['email']) ? $fields['email'] : NULL;
         $this->password = isset($fields['password']) ? $fields['password'] : NULL;
      }

      public function exportVars()
      {
         return get_object_vars($this);
      }
   }
}

namespace Aurora\Modules
{
   use Aurora;
   use Aurora\Models;

   class SignupModule
   {
      /**
       * @param \Aurora\Models\LoginModel $loginModel
	   * @role any
       * @return \JSONResult
       */
      public function index($loginModel)
      {
         return new \HTMLResult("signup\\index", $loginModel);
      }

      /**
       * @param \Aurora\Models\LoginModel $loginModel
	   * @role any
       * @return \HTMLResult
       */
      public function login($loginModel)
      {
         $auth = Aurora\Manager::get("AuthManager");

         $result = $auth->login($loginModel->getLogin(), $loginModel->getPassword());

         if ($result === TRUE)
         {
            return new \HTMLResult("signup\\loginSuccess", $loginModel);
         }
		 
		 $loginModel->setFailure("Account not found");

         return $this->index($loginModel);
      }

      public function exportVars()
      {
         return get_object_vars($this);
      }
   }

   class RightsModule
   {
      private $title = "::Rights";

      public function getlist($accountId, $from=0, $count=10)
      {
         $accounts = Aurora\Manager::get("AccountsManager");
         $vkAccount = $accounts->getByAccountId($accountId, 0, 1);
         $rights = array();
         if (!empty($vkAccount))
         {
            $rights = $accounts->getAccountRights($vkAccount);
         }

         return new \JSONResult(array("data" => $rights));
      }

      public function exportVars()
      {
         return get_object_vars($this);
      }
   }

   class AccountsModule
   {
	  private $title = "::Accounts";
	  
      // main entry point into the app
      public function index()
      {
         $context = array(
            "title" => "Aurora"
         );

         return new \HTMLResult("index", $context);
      }

      // service: retrieves collection of accounts
      public function getlist($from=0, $count=10)
      {
         $state = Aurora\Session::get();
         $accounts = Aurora\Manager::get("AccountsManager");

         $items = $accounts->getActiveAccounts($from, $count);

         $vkAccount = $accounts->findByID("vk01", 0, 1);
         $rights = array();
         if (!empty($vkAccount))
         {
            $rights = $accounts->getAccountRights($vkAccount[0]);
            $accounts->saveAccount($vkAccount[0]);
         }

         $args = array(
            "head" => array("Id", "Name", "Enabled", "Account Type", "Failed Logins"),
            "data" => $items,
            "rights" => $rights,
            "context" => $state->get("notImplemented"),
         );

         //return new HTMLResult("index", $args);
         return new \JSONResult($args);
      }
	  
      public function exportVars()
      {
         return get_object_vars($this);
      }
   }
}

namespace // program execution
{
   $httpService = new HttpService(
      array(
         "accounts" => "Aurora\\Modules\\AccountsModule",
         "signup" => "Aurora\\Modules\\SignupModule",
         "rights" => "Aurora\\Modules\\RightsModule"
      ));
   
   $httpService->restoreState();
   
   Application::run($httpService);
}
